// ==UserScript==
// @name         Pixiv api caller
// @namespace    http://tampermonkey.net/
// @version      1.0.1
// @description  pixiv 体验增强
// @author       HqLin
// @match        https://www.pixiv.net/novel/*
// @grant        GM_xmlhttpRequest
// @grant        GM_setClipboard
// @grant        GM_addStyle
// ==/UserScript==
'use strict';

(async () => {
    GM_addStyle(`
    iframe[name="rectangle"], iframe[name="header"], iframe[name="responsive"] {
        display: none;
    }
    `)

    let ID = getID()
    let DATA = await reFetch()
    // console.log(DATA)

    document.body.addEventListener("keydown", async ev => {
        if (ev.altKey && DATA) {
            ev.preventDefault()
            const currentID = getID()

            // 缓存更新
            if (currentID != ID) {
                DATA = await reFetch()
                ID = currentID
            }
            const page = DATA["novel"][ID]

            switch (ev.key) {
                case "y": {
                    let txt = (page["content"] as string).replaceAll(/\n(?!\n)/g, "\n\n")
                    if (/[`~]/.test(txt)) txt = `\\rules except strikethrough codeinline\n\n${txt}$`
                    GM_setClipboard(txt)
                    break
                }
                case "t": {
                    const taginfo = page["tags"]["tags"].map((info: {tag: any;}) => listify(info.tag))
                    GM_setClipboard(taginfo.join(" "))
                    break
                }
                case "l": {
                    GM_setClipboard(document.URL)
                    break
                }
                case "c": {
                    let series = page["seriesNavData"]
                    GM_setClipboard((series) ? `${series["title"]}——${page["title"]}` : page["title"])
                    break
                }
                case "n": {
                    let series = page["seriesNavData"]
                    if (series) {
                        let next = series["next"]
                        GM_setClipboard(listify((next) ? `${series["title"]}——${next["title"]}` : next["title"]))
                    }
                    break
                }
                default: return
            }
        }
    })

    function listify(title: string): string {
        return title.includes(" ") ? `[[${title}]]` : title
    }

    async function reFetch(): Promise<any> {
        let url = new URL("https://www.pixiv.net/novel/show.php")
        let Id = getID()
        url.searchParams.append("id", Id)
        const doc: Document = await rq({url: url.toString()})
        return JSON.parse(doc.querySelector("meta#meta-preload-data")?.getAttribute("content") ?? "")
    }

    function getID(): string {
        return new URL(document.URL).searchParams.get("id") ?? ""
    }

    async function rq(details: Tampermonkey.Request, timeout = 5000): Promise<Document> {
        return new Promise((res, rej) => {
            details.onerror = rej;
            details.ontimeout = rej;
            details.timeout = timeout;

            details.responseType = "document";
            details.onload = resp => {
                if (resp.status != 200) rej("Not 200!");
                res(resp.response);
            };
            GM_xmlhttpRequest(details);
        });
    }

})()
